package de.dhbw.ka.tit09.picsim.comm;

import gnu.io.CommPortIdentifier;

import java.util.List;

import de.dhbw.ka.tit09.picsim.model.PICModelProvider;

/**
 * management class for serial communication
 * 
 * @author Stefan Unglaub
 */
public class CommManager {

	private List<CommPortIdentifier> portList;
	private String[] portListString;
	private int zaehler;
	private CommSerial commSerial;
	private int[] outputDataBuffer;
	private int[] inputDataBuffer;
	private Thread thread;

	/**
	 * constructor fot the CommManager class
	 */
	public CommManager() {
		commSerial = new CommSerial(); 
		portList = commSerial.getPortList();
												
		portListString = new String[portList.size()];
													
		this.setPortListString();
		outputDataBuffer = new int[9];
		inputDataBuffer = new int[4];
	}

	/**
	 * initiate the serial communication within a new thread
	 * open chosen port
	 * output data while thread is not interrupted
	 * wait for input data
	 * close port
	 */
	public void communicateSerial() {
		thread = new Thread() {
			public void run() {
				commSerial.openPort();
				while (!isInterrupted()) {
					setOutputData(); 
					commSerial.outputData(outputDataBuffer); 

					try {
						Thread.sleep(50);
										
					} catch (InterruptedException e) {
						interrupt();
					}

					if (commSerial.getDataReceived()) {
						setInputData();
						commSerial.clearDataReceived();
					}
				}
				commSerial.closePort();
			}
		};

		thread.start();
	}

	/**
	 * stop serial communication
	 */
	public void stopCommunication() {
		// if(thread.isAlive()){FIXME

		thread.interrupt();
		// }
	}

	/**
	 * write input data into registers
	 */
	private void setInputData() { 
		inputDataBuffer = commSerial.getInputBuffer();

		PICModelProvider
				.getInstance()
				.getSFRegisters()
				.setPORTA(
						((inputDataBuffer[0] - 48) << 4)
								+ (inputDataBuffer[1] - 48)); 

		PICModelProvider
				.getInstance()
				.getSFRegisters()
				.setPORTB(
						((inputDataBuffer[2] - 48) << 4)
								+ (inputDataBuffer[3] - 48));
	}
	
	/**
	 * prepare data for output
	 */
	private void setOutputData() {
		outputDataBuffer[0] = 48 + ((240 & (PICModelProvider.getInstance()
				.getSFRegisters().getTRISA())) >> 4); 
		outputDataBuffer[1] = 48 + (15 & (PICModelProvider.getInstance()
				.getSFRegisters().getTRISA())); 

		outputDataBuffer[2] = 48 + ((240 & (PICModelProvider.getInstance()
				.getSFRegisters().getPORTA())) >> 4); 
		outputDataBuffer[3] = 48 + (15 & (PICModelProvider.getInstance()
				.getSFRegisters().getPORTA())); 
		
		outputDataBuffer[4] = 48 + ((240 & (PICModelProvider.getInstance()
				.getSFRegisters().getTRISB())) >> 4); 
		outputDataBuffer[5] = 48 + (15 & (PICModelProvider.getInstance()
				.getSFRegisters().getTRISB())); 

		outputDataBuffer[6] = 48 + ((240 & (PICModelProvider.getInstance()
				.getSFRegisters().getPORTB())) >> 4); 
		outputDataBuffer[7] = 48 + (15 & (PICModelProvider.getInstance()
				.getSFRegisters().getPORTB()));

		outputDataBuffer[8] = 13;
	}

	/**
	 * @param port port to be used for seriall communication
	 *
	 * set port which should be used
	 */
	public void setPort(int port) {
		commSerial.setPortId(portList.get(port));
	}

	/**
	 * @return list with CommPortIdentifiers of available COM-ports
	 */
	public List<CommPortIdentifier> getPortList() {
		return portList;
	}

	/**
	 * @return String-array with readable COM-port identifiers
	 */
	public String[] getPortListString() {
		return portListString;
	}

	/**
	 * create readable port list
	 */
	private void setPortListString() {
		for (zaehler = 0; zaehler < portList.size(); zaehler++) {
			portListString[zaehler] = portList.get(zaehler).getName();
		}
	}
}
